Skip to content

Feat/dart native skills install#481

Open
Pratikdate wants to merge 12 commits into
StacDev:devfrom
Pratikdate:feat/dart-native-skills-install
Open

Feat/dart native skills install#481
Pratikdate wants to merge 12 commits into
StacDev:devfrom
Pratikdate:feat/dart-native-skills-install

Conversation

@Pratikdate

@Pratikdate Pratikdate commented Jun 6, 2026

Copy link
Copy Markdown

Description

This PR implements a Dart/Flutter-native path for installing Stac skills without requiring Node, npm, or npx, addressing issue #479 (or the relevant issue ID). It adds a new stac skills add CLI command and integrates it into the stac init flow.

Key Changes

  • New Command (stac skills add):
    • Download and extraction of repository ZIP archive using dio and archive.
    • Parses skills/catalog.json from the repository root to find registered skills.
    • Copies specific skill directories to .agents/skills relative to the target directory.
    • Cleans up all downloaded temporary files reliably.
  • Enhanced Security:
    • Prevents path-traversal attacks by validating skillName and skillPath against patterns like .., absolute paths, and backslashes, ensuring all extractions stay within boundaries.
  • Project Initialization Integration:
    • stac init now prompts the user to optionally install Stac agent skills as part of the setup flow.
  • Tests & Documentation:
    • Added unit tests verifying command registration, subcommand registration, and AddCommand attributes.
    • Updated docs/skills.mdx to prioritize the native CLI pathway over npx.

Related Issues

Closes #479 (or insert the correct issue number here)

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Code refactor
  • Build configuration change
  • Documentation
  • Chore

Summary by CodeRabbit

  • New Features
    • Added a new skills command group with an add subcommand to install Stac AI agent skills into projects.
    • Project initialization now prompts users to install skills during setup.
  • Documentation
    • Updated skills installation instructions to use the native Stac CLI (stac skills add) and added an npx alternative.
  • Tests
    • Added/expanded CLI tests (including input safety and temp-folder cleanup) and file-utility tests to validate core filesystem behavior.

Pratikdate and others added 10 commits April 3, 2026 17:19
- Add SkillsCommand with 'stac skills add' subcommand
- AddCommand fetches repo ZIP, parses skills/catalog.json,
  and copies skill dirs into .agents/skills/ — no Node/npm required
- Prompt users in 'stac init' to optionally install agent skills
- Register SkillsCommand in the CLI runner
- Add archive: ^4.0.9 dependency for ZIP extraction
- Update docs/skills.mdx to show Dart-native path first,
  keeping npx as an alternative
- Add tests for SkillsCommand and AddCommand (7 tests pass)

Closes StacDev#480
- Move tempDir cleanup into finally block so temp files are always
  removed even on early return or exception
- Validate skillName and skillPath from catalog.json to prevent
  path-traversal attacks (reject '..', absolute paths, backslashes,
  and enforce canonical boundary checks)
- Accept optional targetDirectory in AddCommand so stac init installs
  skills into the correct project directory, not Directory.current
- Handle non-zero exit from AddCommand in init with a warning instead
  of silently printing success
- Assert non-null and correct type before casting in test to give
  cleaner failure output
@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 87731d68-4db2-4f97-a9dc-b0042cdfcbad

📥 Commits

Reviewing files that changed from the base of the PR and between 533b66c and 35a4a5f.

⛔ Files ignored due to path filters (4)
  • examples/counter_example/pubspec.lock is excluded by !**/*.lock
  • examples/movie_app/pubspec.lock is excluded by !**/*.lock
  • examples/stac_gallery/pubspec.lock is excluded by !**/*.lock
  • packages/stac_cli/pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • packages/stac_cli/lib/src/commands/init_command.dart
  • packages/stac_cli/lib/src/commands/skills/add_command.dart
  • packages/stac_cli/test/commands/cli_commands_test.dart
  • packages/stac_cli/test/utils/file_utils_test.dart
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/stac_cli/lib/src/commands/init_command.dart
  • packages/stac_cli/test/commands/cli_commands_test.dart
  • packages/stac_cli/test/utils/file_utils_test.dart
  • packages/stac_cli/lib/src/commands/skills/add_command.dart

📝 Walkthrough

Walkthrough

This PR introduces a new stac skills add CLI command for downloading and installing AI agent skills from a GitHub repository. The command validates paths to prevent directory traversal attacks, manages the .agents/skills/ installation directory, and integrates an interactive prompt into the initialization workflow. Tests validate command registration and file utility operations. Documentation is updated to reflect the native CLI installation method.

Changes

Skills Installation Feature

Layer / File(s) Summary
AddCommand and helpers
packages/stac_cli/lib/src/commands/skills/add_command.dart
AddCommand downloads HEAD.zip from a GitHub repo (defaulting to https://github.com/StacDev/stac), extracts it, parses skills/catalog.json, validates catalog entries against path-traversal and canonical-boundary checks, and recursively copies skill directories into <target>/.agents/skills/. Includes containsPathTraversal (detects .., absolute paths, backslashes) and _copyDirectory (mirrors contents with recursive bound enforcement).
SkillsCommand group and archive dependency
packages/stac_cli/lib/src/commands/skills_command.dart, packages/stac_cli/pubspec.yaml
Adds SkillsCommand (CLI command group that registers AddCommand as a subcommand) and adds archive: ^4.0.9 dependency for ZIP extraction.
CLI entrypoint registration
packages/stac_cli/bin/stac_cli.dart
Imports and registers SkillsCommand on the main stac CommandRunner, exposing stac skills add.
Init workflow integration
packages/stac_cli/lib/src/commands/init_command.dart
Prompts user during stac init to install skills and runs AddCommand in the project target directory, warning if installation exits non-zero.
CLI and AddCommand tests
packages/stac_cli/test/commands/cli_commands_test.dart
Tests verify CLI command registration (build, init, deploy, skills commands exist with proper metadata; skills exposes add subcommand), AddCommand metadata (name, description, requiresAuth), path-traversal detection via TestAddCommand, and temporary directory cleanup after a failing execution.
FileUtils tests
packages/stac_cli/test/utils/file_utils_test.dart
Unit and integration tests for FileUtils.homeDirectory, configDirectory, ensureConfigDirectory, and file I/O helpers (fileExists, writeFile, readFile, deleteFile) with temp sandbox cleanup.
Docs update
docs/skills.mdx
Replaces prior single npx-centric install framing with native stac skills add as the primary installation method and keeps an npx alternative.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant AddCommand
  participant GitHub
  participant FileSystem
  Client->>AddCommand: execute(repoUrl?)
  AddCommand->>GitHub: GET /archive/HEAD.zip
  GitHub-->>AddCommand: ZIP archive
  AddCommand->>FileSystem: extract ZIP to tempDir
  AddCommand->>FileSystem: read skills/catalog.json
  AddCommand->>AddCommand: validate entries (containsPathTraversal, canonical checks)
  AddCommand->>FileSystem: copy skill dirs -> <target>/.agents/skills/
  AddCommand->>FileSystem: remove tempDir
  AddCommand-->>Client: exit code (0/1)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Suggested reviewers

  • Potatomonsta

Poem

🐰 A skills command hops in with archive in paw,
Downloads and validates with meticulous care,
Path traversal thwarted—no escaping allowed,
Init prompts softly: "Shall I fetch skills here?"
CLI, tests, and docs together—fluffy and fair.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning This PR implements skills installation functionality, but linked issue #479 requires a local 'stac dev' workflow with endpoints, file serving, and apiBaseUrl config—features absent from the changeset. Either correct the linked issue reference to match skills-related issue(s), or implement the required 'stac dev' command, local endpoints, file serving, and apiBaseUrl configuration from issue #479.
Out of Scope Changes check ❓ Inconclusive The changeset focuses on skills installation (new CLI command, documentation, tests) and init integration, which aligns with the PR summary objective but does not match the linked issue #479 requirements. Confirm whether the linked issue #479 is correct or whether a different skills-focused issue (not provided) should be referenced instead.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Feat/dart native skills install' clearly describes the main change: adding a Dart-native skills installation feature to replace the npm/npx-based approach.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
packages/stac_cli/test/commands/cli_commands_test.dart (1)

76-87: 🏗️ Heavy lift

Behavior-critical AddCommand paths still need focused tests.

Current tests validate metadata only. Please add cases for traversal rejection, invalid catalog entries, and temp-dir cleanup in finally so regressions in install safety are caught.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/stac_cli/test/commands/cli_commands_test.dart` around lines 76 - 87,
Add focused unit tests in packages/stac_cli/test/commands/cli_commands_test.dart
for AddCommand that exercise its runtime behavior (not just metadata): add a
test that simulates filesystem traversal attempting to escape the target
directory and assert the command rejects it (reference AddCommand's
traversal/validation logic), add a test that supplies invalid/malformed catalog
entries and asserts the command fails with the expected error handling path
(reference the parsing/validation routine used by AddCommand), and add a test
that forces an error during install to verify the temporary directory is always
deleted in the finally/cleanup block (assert temp-dir does not remain after
failure). Ensure each test constructs AddCommand, invokes the same execution
method used by the CLI (e.g., run/execute), stubs/mocks IO as needed, and
asserts both the failure mode and that cleanup code ran.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/stac_cli/lib/src/commands/skills/add_command.dart`:
- Around line 111-120: The loop that reads catalog entries uses skill['name']
and skill['path'] without type-checking and then casts to String for
_containsPathTraversal, which can throw on non-string values; update the loop in
add_command.dart to first check that skillName and skillPath are Strings (e.g.,
skill['name'] is String and skill['path'] is String) before calling
_containsPathTraversal or casting, and if either is not a String skip the entry
(log a warning via ConsoleLogger.warning mentioning the malformed entry) so a
single bad catalog item cannot abort the install flow.
- Around line 130-137: Replace the fragile prefix check on canonicalized paths
(sourceCanonical.startsWith(repoRootCanonical)) with a robust containment test
using path.isWithin(repoRootCanonical, sourceCanonical) or equality check to
ensure the source is either equal to or strictly inside the repo root; update
the same logic where target/skill paths are validated. In addition, harden
_copyDirectory to avoid symlink traversal by calling Directory.list(...,
followLinks: false) and explicitly handling Link/File/Directory entities
(resolving or skipping links) so you never recursively follow symlinks that
could escape repo/target boundaries; ensure any copied path is re-canonicalized
and validated with path.isWithin before writing to the destination.

---

Nitpick comments:
In `@packages/stac_cli/test/commands/cli_commands_test.dart`:
- Around line 76-87: Add focused unit tests in
packages/stac_cli/test/commands/cli_commands_test.dart for AddCommand that
exercise its runtime behavior (not just metadata): add a test that simulates
filesystem traversal attempting to escape the target directory and assert the
command rejects it (reference AddCommand's traversal/validation logic), add a
test that supplies invalid/malformed catalog entries and asserts the command
fails with the expected error handling path (reference the parsing/validation
routine used by AddCommand), and add a test that forces an error during install
to verify the temporary directory is always deleted in the finally/cleanup block
(assert temp-dir does not remain after failure). Ensure each test constructs
AddCommand, invokes the same execution method used by the CLI (e.g.,
run/execute), stubs/mocks IO as needed, and asserts both the failure mode and
that cleanup code ran.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c18dbf50-3131-4008-9aa7-9e634c67460b

📥 Commits

Reviewing files that changed from the base of the PR and between 29491d8 and 30d4eb6.

⛔ Files ignored due to path filters (1)
  • packages/stac_cli/pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • docs/skills.mdx
  • packages/stac_cli/bin/stac_cli.dart
  • packages/stac_cli/lib/src/commands/init_command.dart
  • packages/stac_cli/lib/src/commands/skills/add_command.dart
  • packages/stac_cli/lib/src/commands/skills_command.dart
  • packages/stac_cli/pubspec.yaml
  • packages/stac_cli/test/commands/cli_commands_test.dart
  • packages/stac_cli/test/utils/file_utils_test.dart

Comment thread packages/stac_cli/lib/src/commands/skills/add_command.dart
Comment thread packages/stac_cli/lib/src/commands/skills/add_command.dart
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants